/*
 *
 */

package org.opu.translator;

import doc2db.fileWorker.ParseHelper;
import java.util.ArrayList;
import java.util.List;
import javax.management.BadAttributeValueExpException;

/**
 *
 * @author yura
 */
public class Lexer {

    private String docText;
    private String tmpltText[];
    private String varLftDlm;
    private String varRgtDlm;

    /** default variable right deliminator */
    public static final String DEFAULT_VAR_RIGHT_DELIM = "$";

    /** default variable left deliminator (like anr right)*/
    public static final String DEFAULT_VAR_LEFT_DELIM = "$";

    Lexer(String docText, String tmpltText[], String varLftDlm, String varRgtDlm) {
        this.docText = docText;
        this.tmpltText = tmpltText;
        this.varLftDlm = varLftDlm;
        this.varRgtDlm = varRgtDlm;
    }

    public Lexer(String docText, String tmpltText[]) {
        this(docText, tmpltText, DEFAULT_VAR_LEFT_DELIM, DEFAULT_VAR_RIGHT_DELIM);
    }



    /**
     * Get the value of variable right delim
     *
     * @return the value of varRgtDlm
     */
    public String getVarRgtDlm() {
        return varRgtDlm;
    }

    /**
     * Set the value of variable right delim
     *
     * @param varRgtDlm new value of varRgtDlm
     */
    public void setVarRgtDlm(String varRgtDlm) {
        this.varRgtDlm = varRgtDlm;
    }


    /**
     * Get the value of variable left delim
     *
     * @return the value of varLftDlm
     */
    public String getVarLftDlm() {
        return varLftDlm;
    }

    /**
     * Set the value of variable left delim
     *
     * @param varLftDlm new value of varLftDlm
     */
    public void setVarLftDlm(String varLftDlm) {
        this.varLftDlm = varLftDlm;
    }


    /**
     * Get the value of dococument text
     *
     * @return the value of docText
     */
    public String getDocText() {
        return docText;
    }

    /**
     * Set the value of document text
     *
     * @param docText new value of docText
     */
    public void setDocText(String docText) {
        this.docText = docText;
    }

    /**
     * Get the value of template text
     *
     * @return the value of tmpltText
     */
    public String[] getTmpltText() {
        return tmpltText;
    }

    /**
     * Set the value of template text
     *
     * @param tmpltText new value of tmpltText
     */
    public void setTmpltText(String tmpltText[]) {
        this.tmpltText = tmpltText;
    }

    /**
     *
     * @return {{name1, name2, ...}, {value1, value2, ...}}
     * @throws javax.management.BadAttributeValueExpException
     * If the pattern does not clearly describe all data. That is,
     * the pattern in the description summarizing data, syntax error.
     */
    public TwoString[] parseDate() throws BadAttributeValueExpException {
        ArrayList<TwoString> list = new ArrayList<TwoString>();

        String restText = docText;
        for (String templates : tmpltText) {

            //TODO:
            // if all info
            if (templates.startsWith("ALL_INFO$") && templates.endsWith("$ALL_INFO")){
                if (templates.length() > 18) {
                    String str = templates.substring(9, templates.length() - 9);
                    String diap = "";
                    int index = str.lastIndexOf("#");
                    if (index > 0){
                        str = str.substring(0, index);
                        diap = str.substring(index, str.length());
                    }
                    
                    if (!isIn(diap)){
                        list.add(new TwoString(str, docText.replace('\"', '`')
                                .replace('\'', '`').replaceAll("LINE_END", " ")));
                    }
                }
                continue;
            }

            // regular parse.
            ArrayList<TypedString> lexems = this.lex(templates);
            
            System.out.println(lexems);

            String text1 = null;
            String var = null;
            String text2 = null;
            for (TypedString lex : lexems) {
                if (lex.getType() == TypedString.TYPE_TEXT){
                    if (text1 == null){
                        text1 = lex.getString();
                    } else if (text2 == null){
                        text2 = lex.getString();
                    } else {
                        System.err.println("anreach statement in templates - " +
                                "to const near: " + text2 + "; " + lex.getString());
                        text2 = lex.getString();
                    }
                } else {
                    if (var != null){
                        if (text1 != null && text2 != null){
                            restText = this.getData(restText, text1, text2, var, list);
                            text1 = text2;
                            text2 = null;
                            var = lex.getString();
                        } else {
                            System.err.println("anreach statement in templates" +
                                    " - to var near:" + var + "; " + lex.getString());
                        }
                    }
                    var = lex.getString();
                }
            }

            if (var != null){
                if (text1 != null && text2 != null){
                    restText = this.getData(restText, text1, text2, var, list);
                } else if (text1 != null){
                    restText = restText.substring(text1.length());
                    list.add(new TwoString(var, restText));
                }
            }
        }

        Object[] toArrayList = list.toArray();
        TwoString ret[] = new TwoString[toArrayList.length];
        System.arraycopy(toArrayList, 0, ret, 0, toArrayList.length);

        return ret;
    }

    /**
     *
     * @param docStr
     * @param text1
     * @param text2
     * @param var
     * @param list
     * @return  rest text
     * @throws javax.management.BadAttributeValueExpException
     * If the pattern does not clearly describe all data. That is,
     * the pattern in the description summarizing data, syntax error.
     */
    private String getData(String docStr, String text1, String text2, String var,
            List<TwoString> list) throws BadAttributeValueExpException{
        
        Token t1 = SimpleTokenizer.expresion(docStr, text1);

        if (t1 == null){
            return docStr;
        }

        Token t2 = null;
        String str = docStr.substring(t1.endPos);
        try {
            t2 = SimpleTokenizer.expresion(str, text2);
        } catch (java.lang.OutOfMemoryError e) {
            throw new BadAttributeValueExpException(str + "<=> delim - " + text2);
        }

        if (t2 == null){
            return docStr;
        }

        t2 = new Token(t2.name, t2.startPos + t1.endPos, t2.endPos + t1.endPos);

        //System.out.println(t1 + " " + t2 + ":" + docStr.replaceAll("\n", "<br>"));
        //System.out.println("\ttext1 " + text1 + "text2 " + text2);

        String varData = docStr.substring(t1.endPos, t2.startPos);
        list.add(new TwoString(var, varData));

        docStr = docStr.substring(t2.startPos);

        return docStr;
    }

    public ArrayList<TypedString> lex(String arr) {
        ArrayList<TypedString> ret = new ArrayList<TypedString>();

        if (arr == null || arr.equals("null")) {
        } else {
            String left = arr;
            while (!left.isEmpty()) {
                int l = left.indexOf(varLftDlm);
                if (l >= 0){
                    String textVar[] = left.split("\\" + varLftDlm, 2);
                    ret.add(new TypedString(textVar[0], TypedString.TYPE_TEXT));
                    left = textVar[1];
                    int r = left.indexOf(varRgtDlm);
                    if (r > 0){
                        textVar = left.split("\\" + varRgtDlm, 2);
                        ret.add(new TypedString(textVar[0], TypedString.TYPE_VAR));
                        left = textVar[1];
                    } else {
                        ret.add(new TypedString(left, TypedString.TYPE_VAR));
                        left = "";
                    }
                } else {
                    ret.add(new TypedString(left, TypedString.TYPE_TEXT));
                    left = "";
                }
            }
        }

        return ret;
    }

    /**
     *  to unnormal array size 2xnormal.lenth
     * <pre>
     * String [][] ret = new String[2][normal.length];
     *
     *  for (int i = 0; i < normal.length; i++) {
     *      ret[0][i] = normal[i].str1;
     *      ret[1][i] = normal[i].str2;
     *  }
     *
     *  return ret;
     * </pre>
     * @param normal normal array
     * @return {{str1[0], str1[1], ...}, {str2[0], str2[1], ...}}
     */
    public static String[][] toUnNormalArr(TwoString[] normal){
        String [][] ret = new String[2][normal.length];

        for (int i = 0; i < normal.length; i++) {
            ret[0][i] = normal[i].str1;
            ret[1][i] = normal[i].str2;
        }

        return ret;
    }

    public static class TwoString{
        public String str1 = "null";
        public String str2 = "null";

        public TwoString(String str1, String str2) {
            this.str1 = str1;
            this.str2 = str2;
        }

        public static String [] toArr(TwoString ts){
            return new String[]{ts.str1, ts.str2};
        }
    }

    public boolean isIn(String str){
        for (String s : str.split(",")) {
            try {
                if (Integer.parseInt(s.trim()) == ParseHelper.tabNum()) {
                    return true;
                }
            } catch (NumberFormatException ex) {
            }
        }
        return false;
    }

}
